﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mahanet.Abyss.PathCalculation
{
	public class LeastSquaresLinearSinglePathOracle : IPathOracle<double, double>
	{
		#region Fields

		private List<DataPoint<double, double>> m_DataPoints = new List<DataPoint<double,double>>();
		private alglib.polynomialfitreport m_LastReport;

		#endregion

		#region Public Properties

		public FunctionApproximation<double, double> Approximation { get; private set; }

		public int DataPointCount
		{
			get { return m_DataPoints.Count; }
		}

		#endregion

		#region Public Methods

		public void AddPointData(DataPoint<double, double> point)
		{
			m_DataPoints.Add(point);
		}

		public void GenerateApproximation()
		{
			int info = 0;
			double[] xValues = m_DataPoints.Select(dataPoint => dataPoint.Paramter).ToArray();
			double[] yValues = m_DataPoints.Select(dataPoint => dataPoint.Value).ToArray();

			alglib.barycentricinterpolant approximation;
			alglib.polynomialfit(xValues, yValues, 3, out info, out approximation, out m_LastReport);
			Approximation = t => alglib.barycentriccalc(approximation, t);
		}

		public double GetCertainty()
		{
			return m_DataPoints.Count == 0 ? 0 : 1.0 - (1.8 / (double)(m_DataPoints.Count + 1));
		}

		public string GetLastReportString()
		{
			return string.Format("On points: Max error {0}, avg error {1}, avg rel error {2}", m_LastReport.maxerror, m_LastReport.avgerror, m_LastReport.avgrelerror);
		}

		#endregion
	}
}